package org.xqh.study.certs;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.xqh.utils.encrypt.EncryptUtils;
import org.xqh.utils.file.ReadTxtFileUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @ClassName GenerateCertTest
 * @Description TODO
 * @Author xuqianghui
 * @Date 2024/7/9 16:42
 * @Version 1.0
 */
@Slf4j
public class CmdGenerateCertTest {

    //openssl genrsa -out root.key 2048
    private final static String gen_key_command = "openssl genrsa -out %s %s"; // 输出文件名, rsa长度 (root.key, 2048)

    //openssl req -new -key root_prod.key -out root_prod.csr -config san.cnf -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=UGREEN Technology Co., Ltd./OU=NAS/CN=ug.link"
    private final static String gen_root_csr_command = "openssl req -new -key %s -out %s -subj \"%s\"";//生成根证书命令

    //openssl x509 -req -days 3650 -in root_prod.csr -signkey root_prod.key -out root_prod.crt -extfile san.cnf -extensions v3_req
    private final static String gen_root_cert_command = "openssl x509 -req -days %s -in %s -signkey %s -out %s";//生成根证书命令

    //openssl req -new -key root_prod.key -out root_prod.csr -config san.cnf -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=UGREEN Technology Co., Ltd./OU=NAS/CN=ug.link"
    private final static String gen_csr_command = "openssl req -new -key %s -out %s -subj \"%s\"";

    //openssl x509 -req -days 3650 -in root_prod.csr -signkey root_prod.key -out root_prod.crt -extfile san.cnf -extensions v3_req
    private final static String issue_cert_command = "openssl x509 -req -days %s -in %s -CA %s -CAkey %s -set_serial 01 -out %s";//签发证书命令

    private final static String cert_path_prod = "D:\\work\\program\\certs\\prod\\%s";//证书路径
    private final static String cert_path_test = "D:\\work\\program\\certs\\test\\%s";//测试环境
    private final static String cert_path_dev = "D:\\work\\program\\certs\\dev\\%s";//测试环境

//    private final static String root_name = "root_prod";//根证书名称
    private final static String root_test = "root_test";//根证书名称
    private final static String root_prod = "root_prod";//根证书名称
    private final static String root_dev = "root_dev";//根证书名称
    private final static String san_name = "san.cnf";//根证书名称

    private final static String cert_name = "";//生成证书名称



    @Data
    public static class CmdExecuteModel {

        private String cmd;

        private Object[] values;

        private String outPath;//输出文件路径

        private boolean result;

        private String output;//输出文件内容

    }

    public static void executeCmd(CmdExecuteModel cmd) {
        String[] cmdArr = cmd.getCmd().split(" ");
        String[] commands = new String[cmdArr.length];
        int j = 0;
        for (int i = 0; i < cmdArr.length; i++) {
            String str = cmdArr[i];
            if (str.contains("%s")) {
                str = String.format(str, cmd.getValues()[j]);
                j++;
            }
            commands[i] = str;
        }
        log.info("execute commands: {}", JSON.toJSONString(commands));
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(commands); // 示例命令

            // 合并错误流和标准输出流（可选）
            processBuilder.redirectErrorStream(true);

            Process process = processBuilder.start();

            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;
            while ((line = reader.readLine()) != null) {
                log.info("execute command result => {}", line);
            }

            int exitCode = process.waitFor();
            if (exitCode == 0) {
                cmd.setResult(true);
            }
        } catch (IOException | InterruptedException e) {
            log.error("", e);
            cmd.setResult(false);
        }

        if(cmd.isResult()){
            String txt = ReadTxtFileUtils.readAllTxt(new File(cmd.getOutPath()));
            log.info("========> {}", txt);
            cmd.setOutput(txt);
        }
    }


    /**
     * 生成根证书
     */
    private static void generateRootCert(String rootName, String certPath){

        //生成私钥
        CmdExecuteModel genCertCmd = new CmdExecuteModel();
        genCertCmd.setCmd(gen_key_command);
        Object[] values = {String.format(certPath, rootName + ".key"), "2048"};
        genCertCmd.setValues(values);
        genCertCmd.setOutPath(String.format(certPath, rootName + ".key"));
        executeCmd(genCertCmd);

        //生成证书请求csr
        CmdExecuteModel csrCmd = new CmdExecuteModel();
        csrCmd.setCmd(gen_root_csr_command);
        Object[] values2 = {String.format(certPath, rootName + ".key"), String.format(certPath, rootName + ".csr"), "/C=CN/ST=guangdong/L=shenzhen/O=UGREEN Technology Co., Ltd./OU=NAS/CN=ug.link"};
        csrCmd.setValues(values2);
        csrCmd.setOutPath(String.format(certPath, rootName + ".csr"));
        executeCmd(csrCmd);

        //生成证书
        CmdExecuteModel crtCmd = new CmdExecuteModel();
        crtCmd.setCmd(gen_root_cert_command);
        Object[] values3 = {"3650", String.format(certPath, rootName + ".csr"), String.format(certPath, rootName + ".key"),
                String.format(certPath, rootName + ".crt")};
        crtCmd.setValues(values3);
        crtCmd.setOutPath(String.format(certPath, rootName + ".crt"));
        executeCmd(crtCmd);
    }

    /**
     * 签发证书
     * @param certName 证书名
     * @param caName  根证书名
     */
    private static void generateIssueCert(String certName, String caName, String certPath, String days){
        //生成证书私钥
        CmdExecuteModel genCertCmd = new CmdExecuteModel();
        genCertCmd.setCmd(gen_key_command);
        Object[] values = {String.format(certPath, certName + ".key"), "2048"};
        genCertCmd.setValues(values);
        genCertCmd.setOutPath(String.format(certPath, certName + ".key"));
        executeCmd(genCertCmd);

        //生成证书CSR
        CmdExecuteModel genCsrCmd = new CmdExecuteModel();
        genCsrCmd.setCmd(gen_csr_command);
        Object[] values2 = {String.format(certPath, certName + ".key"), String.format(certPath, certName + ".csr"),
                "/C=CN/ST=guangdong/L=shenzhen/O=UGREEN Technology Co., Ltd./OU=NAS/CN=ug.link"};
        genCsrCmd.setValues(values2);
        genCsrCmd.setOutPath(String.format(certPath, certName + ".csr"));
        executeCmd(genCsrCmd);

        //签发证书 //openssl x509 -req -days 3650 -in uglink_server.csr -CA root.crt -CAkey root.key -set_serial 01 -out uglink_server.crt
        CmdExecuteModel issueCmd = new CmdExecuteModel();
        issueCmd.setCmd(issue_cert_command);
        Object[] values3 = {days, String.format(certPath, certName + ".csr"), String.format(certPath, caName + ".crt"), String.format(certPath, caName + ".key"),
                String.format(certPath, certName + ".crt")};
        issueCmd.setValues(values3);
        issueCmd.setOutPath(String.format(certPath, certName + ".crt"));
        executeCmd(issueCmd);
    }

    public static void main(String[] args) throws IOException {
        //生成根证书
//        generateRootCert(root_dev, cert_path_dev);
//        generateIssueCert("uglink_client_dev", root_dev, cert_path_dev);
//        generateIssueCert("uglink_server_dev", root_dev, cert_path_dev);

//        generateRootCert(root_prod, cert_path_prod);
//        generateIssueCert("uglink_client_prod", root_prod, cert_path_prod);
//        generateIssueCert("uglink_server_prod", root_prod, cert_path_prod);

        //签发客户端证书
//        generateIssueCert("uglink_client_prod", root_prod, cert_path_prod);

//        generateRootCert(root_test, cert_path_test);
//        generateRootCert(root_test, "D:\\work\\program\\certs\\2root\\%s");
//        generateIssueCert("uglink_client_test", root_test, "D:\\work\\program\\certs\\2root\\%s", "365");
//        generateIssueCert("uglink_server_test", root_test, cert_path_test);

        String crt = "-----BEGIN CERTIFICATE-----\n" +
                "MIIDbDCCAlQCAQEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCQ04xEjAQBgNV\n" +
                "BAgMCWd1YW5nZG9uZzERMA8GA1UEBwwIc2hlbnpoZW4xJDAiBgNVBAoMG1VHUkVF\n" +
                "TiBUZWNobm9sb2d5IENvLiwgTHRkLjEMMAoGA1UECwwDTkFTMRIwEAYDVQQDDAl1\n" +
                "Z25hcy5jb20wHhcNMjQwNzEwMDEwOTQzWhcNMzQwNzA4MDEwOTQzWjB8MQswCQYD\n" +
                "VQQGEwJDTjESMBAGA1UECAwJZ3Vhbmdkb25nMREwDwYDVQQHDAhzaGVuemhlbjEk\n" +
                "MCIGA1UECgwbVUdSRUVOIFRlY2hub2xvZ3kgQ28uLCBMdGQuMQwwCgYDVQQLDANO\n" +
                "QVMxEjAQBgNVBAMMCXVnbmFzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" +
                "AQoCggEBAMYilYIQuDmWxai+VhA4fSgu80xNwIaBIXzwxKNmUqZ5ahPvAhzd2jCQ\n" +
                "AugwnBB1o38vX8q2Pmr6QZkevThSv02cPmL1xZ8Brk0a5fpgPsPY/xRCstZbuj8N\n" +
                "g9dNanNN+ADEDDtk7uMT2aQP3OzkzJy4V2SA+J+QVh26xODsZSep4e4B64f5suER\n" +
                "Kqi7KVYeA17W7CLD2AKq3kddkRD6GhyAxJqPKoHeyxoN88KD2Nu+PVLcq8IPrR9/\n" +
                "lk9qy/816KisCCVaTRZEAXkk0yvftGrs9Be1fR8PzC/oBDQOLCHzctMTzYb0YbUC\n" +
                "XenVIWKeFvXUexT+dwjKBnKg8iCCpgsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA\n" +
                "vJJnDmpWbMg+cAw1b5ACGLKJrk1tRowcNxvVxLaSmSawVCvxcgX+inUharDtVKeo\n" +
                "K+53mDGVXWUVJS826Iw6BfuKXKSc3eTvCWS9JL5V32ih2yjuNiKJc4c60EtJOEot\n" +
                "CAe+wL92RLhSUPESn0rfM4syzEi6DDZaAVLdC1cD2lCEHUyYXpZ6zW/IE3YCw/2P\n" +
                "LOEoDDHLHE3jWS0la6OI+lIebIJbrtA+HOzj1HWaQWwv7R0FZMMyRYZiwE732Hc9\n" +
                "zKGZzpfI0jZM39Y4lnoBT2m3txo0Jq9Q6OOEyUB1Um4kcolrCpi4pIKaseoZFGsj\n" +
                "FotCEURk9IwWNepeIPge+A==\n" +
                "-----END CERTIFICATE-----\n";
        System.out.println(EncryptUtils.getMd5(crt));
    }

}
